package batch.process.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.springframework.util.Log4jConfigurer;

import batch.process.exception.UtilityException;
import batch.process.messages.Messages;


/**
 * Common class for pointing log4j to a file other than the default.
 */
public class Log4jConfigurator {
  private static Log4jConfigurator instance = new Log4jConfigurator();
  private static HashSet configured = new HashSet();
  private Log4jConfigurator()  { }
  
  /**
   * Static method to configure log4j properites.
   * @return Log4jConfigurator.
   */
  public static Log4jConfigurator configure() throws Exception {
    String fileName = System.getProperty("log4j.configuration");
    if (fileName == null) { 
      fileName = "log4j.xml"; 
    }
    
    String propertiesFileList = System.getProperty("log4j.custom.properties");
    if(propertiesFileList != null) {
      StringTokenizer tokenizer = new StringTokenizer(propertiesFileList,",");
      while(tokenizer.hasMoreTokens()) {
        String propertiesFileName = tokenizer.nextToken();
        InputStream is = Log4jConfigurator.class.getClassLoader().getResourceAsStream(propertiesFileName);	
    	if(is == null) {
            String runtime_dir = System.getProperty("runtime_dir");
            if(runtime_dir != null) {
              runtime_dir = runtime_dir.trim();
              if(runtime_dir.length() > 0) {              	                
                is = new FileInputStream((new File(runtime_dir + "/" + propertiesFileName)).getAbsoluteFile());
                if (is == null) {
                	propertiesFileName = "file:" + runtime_dir + "/" + propertiesFileName;
                	is = Log4jConfigurator.class.getClassLoader().getResourceAsStream(propertiesFileName);
                }
              }
            }          
        }        
        
        if(is != null) {
          Properties properties = new Properties();
          properties.load(is);
          Enumeration e = properties.keys();
          while(e.hasMoreElements()) {
            String key = (String)e.nextElement();
            String value = (String)properties.get(key);
            System.setProperty(key, value);
          }
        }
      }
    }
    
    return(configure(fileName));
  }
  
  /**
   * Static method to configure log4j properites.
   * @param fileName String specifying the xml file, must be in the classpath.
   * @return Log4jConfigurator.
   */
  public static Log4jConfigurator configure(String fileName) throws Exception {
    try {
      if(fileName == null) {
        throw new UtilityException(Messages.INVALID_FILENAME.format(new Object[] {fileName}),null);
      }
      synchronized(configured) {
        if(configured.add(fileName)) {
          Log4jConfigurer.initLogging("classpath:" + fileName);
          if (Logger.getRootLogger().isEnabledFor(Priority.DEBUG)) {
            System.out.println("Log4jConfigurator successfully configured with: " + fileName);
          }          
        }
      }
    }
    catch(Exception e)  {
      configured.remove(fileName);
      System.out.println("Log4jConfigurator failed with: " + fileName);
    }
    return(instance);
  }
}
